package scenebuilders;

import javax.media.j3d.Group;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3d;
import javax.vecmath.Vector3f;

import com.sun.j3d.utils.geometry.Cylinder;

public class WiredBuilder {
	Group sceneRoot;	
	Point3f[] vertexArray = null;
			
	public WiredBuilder(Group sceneRoot) {
		this.sceneRoot = sceneRoot;
	}

	public void setVertexArray(float scale,	Point3f[] vertexArray) { 
		for (Point3f p : vertexArray) {
			p.x *= scale;
			p.y *= scale;
			p.z *= scale;
		}
		this.vertexArray = vertexArray;
	}
	
	public void setStripOfVertex(int... vertexIDs) {
		for (int i = 0; i < vertexIDs.length - 1; i++)
		{
			Point3f vertex1 = vertexArray[vertexIDs[i + 0]];
			Point3f vertex2 = vertexArray[vertexIDs[i + 1]];				
			addEdge(vertex1, vertex2);
		}
	}
								
	// prida hranu a otoci ju podla potreby 
	private void addEdge(Point3f vertex1, Point3f vertex2) {
		float vyska = vertex1.distance(vertex2);
		Vector3f stred = new Vector3f(vertex1);
		stred.add(vertex2);
		stred.scale(0.5f);
		Vector3d desiredVector = getDesiredVertor(vertex1, vertex2);
		double angleZ = getAngleInXYPlane(desiredVector);
		double angleX = getAngleInYZPlane(desiredVector);

		Transform3D trns = new Transform3D();
		Transform3D rotX = new Transform3D();
		Transform3D rotZ = new Transform3D();
		trns.setTranslation(stred);
		rotX.rotX(angleX);
		rotZ.rotZ(angleZ);
		trns.mul(rotZ);
		trns.mul(rotX);
		TransformGroup objTrans = new TransformGroup(trns);
		sceneRoot.addChild(objTrans);

		objTrans.addChild(new Cylinder(0.05f, vyska));
	}
	
	static Vector3d defaultVector = new Vector3d(0, 1, 0);
	
	static private Vector3d getDesiredVertor(Point3f vertex1, Point3f vertex2) {
		Vector3d vector2 = new Vector3d(vertex2);
		Vector3d vector1 = new Vector3d(vertex1);
		vector2.sub(vector1);
		return vector2;
	}
	
	static private double getAngleInYZPlane(Vector3d _desiredVector) {
		Vector3d desiredVector = (Vector3d) _desiredVector.clone();		
		desiredVector.z = 0;
		if (desiredVector.length()==0)
			return Math.PI/2;		
		double angle = _desiredVector.angle(desiredVector);
		if (_desiredVector.z < 0)
			angle = -1 * angle;
		return angle;
	}

	static private double getAngleInXYPlane(Vector3d _desiredVector) {
		Vector3d desiredVector = (Vector3d) _desiredVector.clone();
		desiredVector.z = 0;
		if (desiredVector.length()==0)
			return 0;		
		double angle = defaultVector.angle(desiredVector);
		Vector3d vs = new Vector3d(); 
		vs.cross(defaultVector, desiredVector);
		if (vs.z < 0)
			angle = -1 * angle;
		return angle;		
	}
}
